from qturboframe.lib.webdriver.remote.webelement import WebElement
from qturboframe.lib.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.by import By
from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.report.log import logger

from .base_element import BaseElement

class CheckBox(BaseElement):
    """
    Jres2.0的复选框操作

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _elements: 复选框元素列表，list
     - timeout: 步骤操作的超时时间

    :Raises:
        当element_para类型不对时则抛出AttributeError异常

    :Example:
     - 例1: CheckBox(webelement)
     - 例2: CheckBox({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: CheckBox({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: CheckBox({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    """

    def __init__(self, element_para, father=None, timeout=5):
        if isinstance(element_para, list) and len(element_para) > 0:
            if isinstance(element_para[0], WebElement):
                self._elements = element_para
                self._driver = element_para[0]._parent
                self.timeout = timeout
            else:
                raise AttributeError('element_para参数不正确，需是WebElement的集合！')
        elif not isinstance(element_para, dict):
            raise AttributeError('element_para参数类型不正确！')
        else:
            if father is None:
                raise AttributeError('未定位元素，father参数不能为None！')
            if isinstance(father, WebDriver):
                self._driver = father
                self.timeout = timeout
            elif isinstance(father, WebElement):
                self._driver = father._parent
                self.timeout = timeout
            else:
                raise AttributeError('father参数类型不正确！')
            key_list = [By.ID, By.NAME, By.CLASS_NAME, By.TAG_NAME, By.LINK_TEXT,
                        By.PARTIAL_LINK_TEXT, By.CSS_SELECTOR, By.XPATH]
            element_by = ''
            element_value = ''
            assist = ''
            for key, value in element_para.items():
                if key in key_list:
                    element_by = key
                    element_value = value
                else:
                    assist += '{}:{},'.format(key, value)
            assist = assist.strip(',')
            self._elements = father.find_elements_by_attribute(
                element_by, element_value, assist, self.timeout)

    def set_value(self, value=['all']):
        """
        Jres2.0的复选框选择

        :Args:
         - value: 选择项的文本

        :Example:
         - 例1: checkbox.set_value()
         - 例2: checkbox.set_value("value")
        """
        # 排除非复选框元素
        i = 0
        while i < len(self._elements):
            if 'checkbox' in self._elements[i].get_attribute('type'):
                i += 1
            else:
                self._elements.remove(self._elements[i])
        # 获取input对应的label
        labels = list()
        for inputele in self._elements:
            label = inputele.find_element_by_attribute('xpath', './parent::*', timeout=self.timeout)
            labels.append(label)
        num = 0
        # 选择前先全部清空
        for i in range(0, len(self._elements)):
            if self._elements[i].get_attribute('checked'):
                # labels[i].secure_click()
                BaseElement(labels[i]).click()
        if value[0] == "all":
            for i in range(0, len(self._elements)):
                if not self._elements[i].get_attribute('checked'):
                    # labels[i].secure_click()
                    BaseElement(labels[i]).click()
                    num += 1
        else:
            for text in value:
                for i in range(0, len(self._elements)):
                    total_text = self._elements[i].find_element_by_attribute(
                        'xpath', './parent::*', timeout=self.timeout).text.strip()
                    try:
                        button_text = self._elements[i].find_element_by_attribute(
                            'xpath', './parent::*/button', timeout=self.timeout).text.strip()
                    except:
                        pass
                    if button_text:
                        chkbox_text = total_text.replace(button_text, '')
                    else:
                        chkbox_text = total_text
                    # chkbox_text = self._elements[i].find_element_by_attribute(
                    #     'xpath', './parent::*', timeout=self.timeout).text.strip()
                    if text == chkbox_text and not self._elements[i].get_attribute('checked'):
                        # labels[i].secure_click()
                        # BaseElement(labels[i]).click()
                        BaseElement(labels[i].find_element_by_attribute('xpath', './input')).click()
                        num += 1
                        break
                else:
                    logger.warn('未选中选项：' + text)
        return num

    def verify(self):
        """
        Jres2.0的复选框验证是否成功

        :Returns:
            验证成功返回True，验证失败返回False，无验证结果则返回None

        :Example:
         - 例1: checkbox.verify()
        """
        div_verify = self._elements[0].find_element_by_attribute('xpath', './parent::*/parent::*/parent::div',
                                                         timeout=self.timeout)
        classValue = div_verify.get_attribute('class')
        if 'u-radio-group' in classValue:
            if 'm-verify-success' in classValue:
                return True
            elif 'm-verify-error' in classValue:
                return False
            else:
                return None
        else:
            div_elements = div_verify.find_elements_by_attribute('xpath', './descendant::div',
                                                                 timeout=self.timeout)
            for div_element in div_elements:
                classValue = div_element.get_attribute('class')
                if 'u-radio-group' in classValue:
                    if 'm-verify-success' in classValue:
                        return True
                    elif 'm-verify-error' in classValue:
                        return False
                    else:
                        return None

    def get_error_info(self):
        """
        获取Jres2.0的复选框验证错误信息

        :Returns:
            返回验证错误的文本信息

        :Example:
         - 例1: checkbox.get_error_info()
        """
        errorInfo = ""
        updiv = self._elements[0].find_element_by_attribute('xpath:./parent::*/parent::*/parent::div',
                                                    timeout=self.timeout)
        classValue = updiv.get_attribute('class')
        if 'u-radio-group' in classValue:
            div_error = updiv.find_element_by_attribute(
                'xpath', './div[@class=\"m-verify-tip\"]/div[@class=\"verify-tip-inner\"]',
                timeout=self.timeout)
            errorInfo = div_error.text
        else:
            div_elements = updiv.find_elements_by_attribute('xpath', './descendant::div',
                                                            timeout=self.timeout)
            for div_element in div_elements:
                classValue = div_element.get_attribute('class')
                if 'u-radio-group' in classValue:
                    div_error = div_element.find_element_by_attribute(
                        'xpath', './div[@class=\"m-verify-tip\"]/div[@class=\"verify-tip-inner\"]',
                        timeout=self.timeout)
                    errorInfo = div_error.text
        return errorInfo

    def is_readonly_for_checkbox(self):
        """
        检查Jres2.0的复选框的选项是否只读

        :Args:

        :Returns:
            控件组均是只读状态则返回True，否则返回False

        :Example:
         - 例1: checkbox.is_readonly_for_checkbox()
        """
        for inputele in self._elements:
            if not inputele.is_readonly():
                return False
        else:
            return True

    def is_default(self, value):
        """
        检查Jres2.0的复选框默认值

        :Args:
         - value: 待检查的选项值

        :Returns:
            匹配返回True，否则返回False

        :Example:
         - 例1: checkbox.is_default("value")
        """
        for text in value:
            i = 0
            for inputele in self._elements:
                status = inputele.get_attribute('checked')
                if status:
                    chkbox_text = inputele.find_element_by_attribute('xpath', './parent::*').text
                    if chkbox_text == text:
                        i += 1
            if i < 1:
                logger.getlogger().error('复选框默认值与校验值不一致！')
                return False
        else:
            return True

    def uncheck_all_checkboxes(self):
        """
        使Jres2.0的复选框为不选中

        :Example:
         - 例1: checkbox.un_check_checkboxes()
        """
        for checkbox in self._elements:
            if checkbox.is_selected():
                try:
                    checkbox.click()
                except:
                    #有的checkbox在设计中会被别的tag遮挡住，直接点击checkbox会抛出 element not visible的异常
                    #如果抛出此异常则查找其父级元素然后点击
                    try:
                        checkbox.find_element_by_attribute(By.XPATH,"..").click()
                    except Exception as msg:
                        self._driver.execute_script("arguments[0].click();", checkbox)

    def check_all_checkboxes(self):
        """
        使Jres2.0的复选框为选中

        :Example:
         - 例1: checkbox.check_all_checkboxes()
        """
        for checkbox in self._elements:
            if not checkbox.is_selected():
                BaseElement(checkbox).click()
                if not checkbox.is_selected():
                    try:
                        checkbox.find_element_by_attribute(By.XPATH,"..").click()
                    except Exception as msg:
                        if 'element not visible' not in str(msg):
                            raise SeleniumError(str(msg))

    def uncheck_by_text(self, text):
        # 排除非复选框元素
        i = 0
        while i < len(self._elements):
            if 'checkbox' in self._elements[i].get_attribute('type'):
                i += 1
            else:
                self._elements.remove(self._elements[i])

        # 获取input对应的label
        labels = list()
        for checkbox in self._elements:
            label = checkbox.find_element_by_attribute('xpath', './parent::*', timeout=self.timeout)
            if BaseElement(label).get_text().strip() == text.strip():
                if checkbox.is_selected():
                    BaseElement(checkbox).click()
                    break
